home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
FishMarket 1.0
/
FishMarket v1.0.iso
/
fishies
/
051-075
/
disk_059
/
browser
/
browser.c
< prev
next >
Wrap
C/C++ Source or Header
|
1992-05-06
|
16KB
|
557 lines
/*
* browser - Rummage around on disks.
*
* copyright (c) 1986, Mike Meyer
*
* Permission is hereby granted to distribute this program, so long as this
* source file is distributed with it, and this copyright notice is not
* removed from the file.
*
* modified Mark Schretlen 86-10-04
* last update 87-01-11
*
*/
#include <exec/types.h>
#include <graphics/gfxbase.h>
#include <libraries/dos.h>
#include <libraries/dosextens.h>
#include <intuition/intuition.h>
#include <stdio.h>
#define INTUITION_REV 1L
#define GRAPHICS_REV 1L
#define LONGEST_NAME 80 /* Longest file name we can deal with */
#define LONGEST_LINE 256 /* Longest line we will deal with */
#define AVG_LINE_LENGTH 62 /* A guess, tune it if you need to */
#define FILEINFOBLOCKSIZE 256 /* m.e.s. for memory allocation in Add_Dir */
#define FUDGE 6L /* A fudge factor for the scroll bar */
#define UP_GADGET 0 /* switch flags for Gadget ID */
#define DOWN_GADGET 1
#define SCROLL_GADGET 2
#define NEW_FILE 3
#define GWIDTH 14 /* Width of gadget */
#define GHEIGHT 9
struct SpriteImage {
UWORD posctl[2];
UWORD sprdata[2][15];
UWORD reserved[2];
};
#define FIRST 18L
/*
* Gadget structures put in browser.h
*/
#include "browser.h"
/*
* doggy sprite (M.E.S. 86-10-01)
*/
struct SpriteImage Doggy[34] = {
0x0002, 0x0002, /* VStart, VStop */
0x0002, 0x0,
0x3A02, 0x0,
0x2A02, 0x1000,
0xFA02, 0x8000,
0xF9FE, 0x0,
0xFFFE, 0x0,
0x1FFE, 0x0,
0x1FFE, 0x0,
0x1FFC, 0x0,
0x1FFC, 0x0,
0x0A14, 0x0,
0x0A14, 0x0,
0x0A14, 0x0,
0x0A14, 0x0,
0x0A14, 0x0,
0x0000, 0x0000 }; /* End of Sprite */
/*
* Now, the window for it all
*/
struct NewWindow New_Window = {
0, 0, 640, 200, /* Full screen */
-1L, -1L, /* Default pens */
MENUPICK | CLOSEWINDOW /* I want to know about menupicks */
| GADGETUP, /* Window closes and gadgets */
ACTIVATE /* Standard window */
| SMART_REFRESH | NOCAREREFRESH | SIZEBBOTTOM
| WINDOWSIZING | WINDOWDEPTH | WINDOWCLOSE | WINDOWDRAG,
&Down_Gadget, /* Add scroll gadget */
/*(struct Image *)*/ NULL,
"Browser 1.2 by Mark Schretlen ;original-Mike Meyer;scroll-B.Leivian", /* Title */
/*(struct Screen *)*/NULL,
/*(struct BitMap *)*/NULL,
100, 57, /* Minimum sizes */
640, 200, /* Maximum sizes */
WBENCHSCREEN /* and put it on the workbench */
} ;
/*
* My very own variables (mostly for done)
*/
struct Window *My_Window = NULL ;
static FILE *infile = NULL ; /* Current input file */
static void Page_File(unsigned short) ;
/* file statistics M.E.S. 87-01-11 */
struct FStatistics *stats;
struct FStatistics fileInformation = { 0L,0L,0L };
/*
* And someone else's variables
*/
struct IntuitionBase *IntuitionBase ;
struct GfxBase *GfxBase ;
extern struct Menu *AutoMenu ;
/*
* Finally, declare the string twiddling functions as voids
*/
void strcat(char *, char *), strcpy(char *, char *) ,
strncat(char *, char *, int) ;
main() {
register struct IntuiMessage *message,*GetMsg(struct MsgPort *);
register unsigned short class, code ;
APTR address;
USHORT gadID;
/* Set up the world this lives in */
if ((IntuitionBase = (struct IntuitionBase *)
OpenLibrary("intuition.library", INTUITION_REV)) == NULL)
done(20, "can't open intuition library") ;
if ((GfxBase = (struct GfxBase *)
OpenLibrary("graphics.library", GRAPHICS_REV)) == NULL)
done(20, "can't open graphics library") ;
/* set up the scroll bar */
prop.Flags = FREEVERT | AUTOKNOB | KNOBHIT ;
prop.VertBody = 0x1000;
if ((My_Window = (struct Window *) OpenWindow(&New_Window)) == NULL)
done(20, "can't open the window") ;
SetAPen(My_Window -> RPort,3) ; /* Should be default! */
show_message("Pick Disk with Menu Button ");
/* Set up the first menu level */
Menu_Init() ;
Menu_Add("disks ", 1L) ;
Menu_Item_Add("df0:", ITEMENABLED, 0L, 0) ;
Menu_Item_Add("df1:", ITEMENABLED, 0L, 0) ;
Menu_Item_Add("df2:", ITEMENABLED, 0L, 0) ;
Menu_Item_Add("DH0:", ITEMENABLED, 0L, 0) ;
Menu_Item_Add("RAM:", ITEMENABLED, 0L, 0) ;
Menu_Item_Add("VDK:", ITEMENABLED, 0L, 0) ;
SetMenuStrip(My_Window, AutoMenu) ;
SetPointer(My_Window, Doggy,15,16,0,-4);
/* Now spin on messages, handling them as they arrive */
for (;;) {
Wait(1L << (long) My_Window -> UserPort -> mp_SigBit) ;
while (message = GetMsg(My_Window -> UserPort)) {
class = message -> Class ;
code = message -> Code ;
address = message -> IAddress;
ReplyMsg(message) ;
switch (class) {
case CLOSEWINDOW:
done(0, NULL) ;
case MENUPICK:
if (code != MENUNULL)
Examine_Menu_Pick(code) ;
break ;
case GADGETUP:
gadID = ((struct Gadget *)address) -> GadgetID;
Page_File(gadID);
break ;
default:
printf("browser: intuition event 0x%x\n", class) ;
done(20, "unexpected intution event") ;
break ;
}
}
}
done(20, "broke out of never-breaking loop!") ;
}
/*
* Examine_Menu_Pick - takes a menu pick, and twiddles the state variables
* to match that pick.
*/
static
Examine_Menu_Pick(Menu_Number)
unsigned short Menu_Number;
{
register unsigned short level, i, dirp ;
register char *cp ;
char *name, *strchr(char *,int) ;
struct MenuItem *ItemAddress(struct Menu *, unsigned short) ;
/* State variables that describe the current directory */
static char Dir_Name[LONGEST_NAME] ;
static unsigned short Menu_Level = 0 ;
name = ((struct IntuiText *)
(ItemAddress(AutoMenu,Menu_Number) -> ItemFill)) -> IText ;
level = MENUNUM(Menu_Number) ;
/* Got what we want, so clear the menu to avoid confusing the user */
ClearMenuStrip(My_Window);
OffGadget((APTR)&Scroll_Gadget, My_Window, NULL);
OffGadget((APTR)&Up_Gadget, My_Window,NULL);
OffGadget((APTR)&Down_Gadget, My_Window,NULL);
SetWindowTitles(My_Window,"Browser 1.2 by Mark Schretlen (original by Mike Meyer) ",-1);
/* set dirp to FALSE if the name is not a directory or disk */
dirp = (strchr(name, '/') != NULL || strchr(name, ':') != NULL) ;
/* First, set the directory name right */
if (level > Menu_Level) /* Not possible, die */
done(20, "impossible menu value returned") ;
else if (level == 0) /* picked a new disk */
Dir_Name[0] = '\0' ;
else if (level < Menu_Level) { /* Throw away some levels */
for (i = 1, cp = strchr(Dir_Name, ':'); i < level; i++) {
if (cp == NULL) done(20, "broken file name") ;
cp = strchr(cp, '/') ;
}
if (cp == NULL) done(20, "broken file name") ;
*++cp = '\0' ;
}
/* else Menu_Level == level, chose a file at current level */
/* Now, fix up the menu and it's state variable */
while (Menu_Level > level) {
Menu_Level-- ;
Menu_Pop() ;
}
/* If we added a directory, tack it onto the name */
if (dirp) {
Menu_Level++ ;
strncat(Dir_Name, name, LONGEST_NAME - strlen(Dir_Name) - 1) ;
}
/* Now, tell the user all about it */
if (dirp)
Add_Dir(Dir_Name, name) ;
else
Display_File(Dir_Name, name) ;
SetMenuStrip(My_Window, AutoMenu) ;
}
/*
* Add_Dir - given a dir and a name, add the menu name with the files in
* dir as entries.
*/
static
Add_Dir(dir, name) char *dir, *name; {
struct FileInfoBlock *File_Info ;
register char *last_char ;
register struct FileLock *my_lock, *Lock(char *, int) ;
unsigned short count ;
static char Name_Buf[LONGEST_NAME] ;
File_Info = (struct FileInfoBlock *)AllocMem(FILEINFOBLOCKSIZE,0);
/* Fix up the trailing / if it needs it */
last_char = &dir[strlen(dir) - 1] ;
if (*last_char == '/') *last_char = '\0' ;
/* Now, start on the directory */
if ((my_lock = Lock(dir, ACCESS_READ)) == NULL) {
done(20, "can't get lock on file") ;
}
if (!Examine(my_lock, File_Info)) done(20, "can't examine file") ;
if (File_Info -> fib_DirEntryType < 0)
done(20, "Add_Dir called with a non-directory") ;
Menu_Add(name, TRUE) ;
SetAPen(My_Window -> RPort,3) ;
show_message("Loading Directory ");
for (ExNext(my_lock, File_Info), count = 0;
IoErr() != ERROR_NO_MORE_ENTRIES;
ExNext(my_lock, File_Info), count++)
if (File_Info -> fib_DirEntryType < 0)
/* file */
Menu_Item_Add(File_Info -> fib_FileName, ITEMENABLED, 0L, 0) ;
else {
/* directory */
strcpy(Name_Buf, File_Info -> fib_FileName) ;
strcat(Name_Buf, "/");
Menu_Item_Add(Name_Buf, ITEMENABLED, 0L, 0) ;
}
if (count == 0) Menu_Item_Add("EMPTY", 0L, 0L, 0) ;
show_message("Directory Available ");
/* Put everything back */
if (*last_char == '\0') *last_char = '/' ;
FreeMem(File_Info,FILEINFOBLOCKSIZE);
UnLock(my_lock) ;
}
/*
* Display_File - given a directory path and file name, put the first page of
* the file in the window.
*/
long aprox_lines,file_size;
static long Page_Length = 22L;
static
Display_File(dir, name)
char *dir, *name;
{
static char File_Name[LONGEST_NAME];
FILE *fopen();
long ftell();
long i,pages;
extern char *ChangeToString();
extern FILE *parsefile();
extern struct FStatistics *stats,fileInformation;
char *num_of_lines,*num_of_bites;
stats = &fileInformation;
/* Get the file name */
strcpy(File_Name, dir);
strcat(File_Name, name);
if (infile != NULL)
fclose(infile);
if ((infile = fopen(File_Name, "r")) == NULL) {
#ifdef DEBUG
printf("Can't open File: %s\n", File_Name) ;
#endif
done(20, "can't open file") ;
}
/* set up the prop gadget for scrolling */
infile = parsefile(infile);
aprox_lines = stats->lines;
file_size = stats->bites;
prop.Flags = FREEVERT | AUTOKNOB;
if (Page_Length >= aprox_lines)
i = 0xFFFF;
else
{
pages = aprox_lines/Page_Length;
if (aprox_lines%Page_Length != 0) pages++;
i = 0xFFFF / pages; /* FFFF=100% - 0000=0% */
}
prop.VertBody = i;
prop.VertPot = 0L;
fseek(infile, 0L, 0);
if (Page_Length < aprox_lines)
{
OnGadget((APTR)&Down_Gadget,My_Window,NULL);
OnGadget((APTR)&Up_Gadget,My_Window,NULL);
/* enable the scroll bar */
OnGadget((APTR)&Scroll_Gadget, My_Window, NULL);
}
SetWindowTitles(My_Window,"Browser 1.2 **** To page, hit appropriate arrow gadget. ****",-1);
Move(My_Window->RPort,FIRST + 5L ,(long)(My_Window->Height - 5L));
Text(My_Window->RPort," ",45L);
Move(My_Window->RPort,FIRST + 5L ,(long)(My_Window->Height - 5L));
SetAPen(My_Window->RPort,3);
/* SetSoftStyle(My_Window->RPort, FSF_UNDERLINED,255); */
Text(My_Window->RPort,name,(long)strlen(name));
Text(My_Window->RPort," ",3L);
num_of_bites = ChangeToString(file_size);
Text(My_Window->RPort,num_of_bites,(long)strlen(num_of_bites));
Text(My_Window->RPort," bytes",6L);
Text(My_Window->RPort," ",3L);
num_of_lines = ChangeToString(aprox_lines);
Text(My_Window->RPort,num_of_lines,(long)strlen(num_of_lines));
Text(My_Window->RPort," lines",6L);
SetAPen(My_Window->RPort,1);
/* SetSoftStyle(My_Window->RPort, FS_NORMAL,255); */
Move(My_Window->RPort,FIRST,17L);
Page_File((USHORT)NEW_FILE); /* Down from page 0 */
}
/*
* Page_File - move the file up or down one "page"
*/
static void
Page_File(direction)
USHORT direction;
{
long where;
static char buffer[LONGEST_LINE];
static char edited[84]; /* allow room for a tab at end */
static long old_pos;
static long bites_this_page;
static long next_page;
static long size;
int end_flag = 0;
long Line_Length;
int i,j;
long new_pos;
char *p;
if (infile == NULL) return ;
Page_Length = ((My_Window -> Height) - 20) / 8 ;
Line_Length = (My_Window -> Width - (3+FIRST)) / 8;
switch(direction)
{
case UP_GADGET:
new_pos = old_pos;
old_pos = 1L;
break;
case DOWN_GADGET:
new_pos = next_page;
break;
case SCROLL_GADGET:
/* compute new position based on the users scroll bar pot */
new_pos = (file_size * prop.VertPot) / 0xFFFF;
break;
case NEW_FILE:
bites_this_page = 0L;
next_page = 0L;
new_pos = 0L;
old_pos = 1L;
size = 0L;
break;
}
if (new_pos < 0) new_pos = 0L;
/* if past end of file, back up approx 1/2 page */
if (new_pos > file_size)
new_pos = file_size - (bites_this_page / 2);
if ( new_pos == old_pos ) return; /* no change */
where = (new_pos * 0xFFFF)/file_size ;
ModifyProp(&Scroll_Gadget,My_Window,NULL,prop.Flags,0,where,0,prop.VertBody);
old_pos = (new_pos + (size +2)) - bites_this_page ; /* backup one page */
bites_this_page = 0L;
fseek(infile, new_pos, 0);
/* discard a partial line */
if (new_pos)
fgets(buffer, LONGEST_LINE, infile);
/* now put out one page's worth of the file's data */
for (where = 17L, j = Page_Length; j--; where = where + 8L)
{
Move(My_Window -> RPort,FIRST,where ) ;
/* blank the buffer first */
for (i = 0; i < 80; i++)
edited[i] = ' ';
if (!end_flag)
{
if (fgets(buffer, LONGEST_LINE, infile) == NULL)
end_flag = TRUE;
else
{
size = strlen(buffer);
bites_this_page = size + bites_this_page;
/* remove the newline */
buffer[size-1] = '\0';
size--;
p = buffer;
size = 0;
/* edit the buffer for tabs and non-printables */
while(*p)
{
if (*p == '\t')
{
do {
edited[size++] = ' ';
} while(size&3);
}
else if(*p < ' ')
{
edited[size++] = '^';
edited[size++] = *p + '@';
} else
edited[size++] = *p;
p++;
/* mark the line as longer than the window */
if (size >= Line_Length)
{
edited[size-1] = '>';
break;
}
}
}
}
Text(My_Window -> RPort, edited, Line_Length);
} /* for 1 page to size of window */
next_page = (bites_this_page + new_pos) - (size + 2);
return;
}
/*
* done - just close everything that's open, and exit.
*/
static
done(how, why)
int how;
char *why;
{
if (My_Window) {
ClearMenuStrip(My_Window) ;
Menu_Clear() ;
CloseWindow(My_Window) ;
}
if (GfxBase) CloseLibrary(GfxBase) ;
if (IntuitionBase) CloseLibrary(IntuitionBase) ;
if (infile) fclose(infile) ;
if (why)
printf("browser: %s\n", why) ;
(void) OpenWorkBench() ;
exit(how) ;
}
show_message(s)
char *s;
{
Move(My_Window -> RPort, FIRST, 17L);
Text(My_Window -> RPort, s, (long) strlen(s));
Move(My_Window -> RPort, FIRST, 25L);
Text(My_Window -> RPort, " ", 20L);
}